package org.example.redisson;

import cn.hutool.core.lang.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.concurrent.TimeUnit;

/**
 * @Classname RedisLockImpl
 * @Description 封装redis分布锁加锁解锁
 * @Date 2021/3/24 4:16 下午
 *
 *
 * 上述代码的主要逻辑为：在对程序执行尝试加锁操作时，首先生成一个uuid，将生成的uuid绑定到当前线程，并将传递的key参数操作Redis中的key，
 * 生成的uuid作为Redis中的Value，保存到Redis中，
 * 同时设置超时时间。当执行解锁操作时，首先，判断当前线程中绑定的uuid是否和Redis中存储的uuid相等，只有二者相等时，
 * 才会执行删除锁标志位的操作。这就避免了一个线程对程序进行了加锁操作后，其他线程对这个锁进行了解锁操作的问题。
 * @Created by xiangjd
 */
public class RedisLockImpl implements RedisLock {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //把加锁和解锁放在同一个线程里,防止不同线程之间串改
    private ThreadLocal<String> threadLocal = new ThreadLocal<String>();

    @Override
    public boolean tryLock(String key, long timeout, TimeUnit unit) {
        String uuid = UUID.randomUUID().toString();
        threadLocal.set(uuid);
        return stringRedisTemplate.opsForValue().setIfAbsent(key, uuid, timeout, unit);
    }

    @Override
    public void releaseLock(String key) {
        //当前线程的uuid和redis中的uuid一样才能进行删除
        if (threadLocal.get().equals(stringRedisTemplate.opsForValue().get(key))) {
            stringRedisTemplate.delete(key);
        }
    }
}
